﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Transactions;
using System.Web.Mvc;
using System.Web.Security;
using BusinessLibrary;
using MMSWebsite.Business;
using MMSWebsite.DataAccessManagement;
using MMSWebsite.DataAccessManagement.AssetManagement;
using MMSWebsite.Models;

namespace MMSWebsite.Controllers
{
    public class CusMgnController : Controller
    {
        readonly MMSEntities _entities = new MMSEntities();
        private CustomerAccessProvider _cap = new CustomerAccessProvider();
        AssetProvider _ap = new AssetProvider();
        EmployeeAccessProvider _eap = new EmployeeAccessProvider();
        FVAllocation _allocation = new FVAllocation();
        
        static List<Customer> _allocateCus;
        public static string _nameView = "Allocation";

        #region Search Allocation

        public ActionResult Search(string keyName, string keyCode, string keyCity, string keyDistrict, string keyResp, bool keyAccepted, bool keyRefused)
        {
            var searchCus = _allocateCus;
            searchCus = Searching(searchCus, keyName, keyCode, keyCity, keyDistrict, keyResp, keyAccepted, keyRefused);
            if (_nameView != "ListCustomer")
                return PartialView("ListCustomerPartial", searchCus.ToList());
            else return PartialView("ListCusPartial", searchCus.ToList());
        }

        private List<Customer> Searching(List<Customer> searchCus, string keyName, string keyCode, string keyCity, string keyDistrict, string keyResp, bool keyAccepted, bool keyRefused)
        {
            if (keyName != "") searchCus = searchCus.Where(x => x.Name.ToLower().Contains(keyName.ToLower())).ToList();
            if (keyCode != "") searchCus = searchCus.Where(x => x.Code.Contains(keyCode)).ToList();
            if (keyCity != "") searchCus = searchCus.Where(x => x.Area.CityName == keyCity).ToList();
            if (keyDistrict != "") searchCus = searchCus.Where(x => x.Area.DistrictName == keyDistrict).ToList();
            if (keyResp != "")
                searchCus =
                    searchCus.Where(x => x.ResponsibleEmp.Employee.Name.ToLower().Contains(keyResp.ToLower())).ToList();
            if (keyAccepted)
                searchCus = searchCus.Where(x => x.Status.value == Constants.STR_TYPE_STATUS_ACCEPTED).ToList();
            if (keyRefused)
                searchCus = searchCus.Where(x => x.Status.value == Constants.STR_TYPE_STATUS_REFUSED).ToList();
            //set value viewbag data again
            SetViewBagData(null);
            return searchCus;
        }

        #endregion

        #region Allocation Board
        /// <summary>
        /// Get List Of Customer Informations
        /// Vert Method: GET
        /// Url template: /CusMgn/
        /// </summary>
        /// <returns>List View</returns>
        //[MyAuthorize(Roles = "Admin_TPHCM,Admin_HaNoi,Reviewer")]
        public ActionResult Allocation()
        {
            try
            {
                _nameView = "Allocation";
                SetViewBagData(null);
                _allocateCus = _cap.GetAllocationCus();
                return View(_allocateCus.ToList());
            }
            catch (Exception ex)
            {
                // To do: return error view or notify message
                return View();
            }
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Allocation(List<Customer> List)
        {
            //get emp has Responsibility & Start day + endday
            var filterlistByEmp = List.Where(c => c.ResponsibleEmp.Employee.Name != null).ToList();
            var filterlistByDate = List.Where(c => c.StartDay != null).ToList();

            //check _allocateCus is edited column Responsibility
            if (filterlistByEmp.Count != 0)
            {
                foreach (var customer in filterlistByEmp)
                {
                    var cus = _allocateCus.FirstOrDefault(x => x.Id == customer.Id);
                    if (cus != null) cus.ResponsibleEmp = customer.ResponsibleEmp;
                }
            }
            //check _allocateCus is edited column start day and endday
            if (filterlistByDate.Count != 0)
            {
                foreach (var customer in filterlistByDate)
                {
                    var cus = _allocateCus.FirstOrDefault(x => x.Id == customer.Id);
                    if (cus != null)
                    {
                        if (customer.StartDay != null)
                        {
                            cus.StartDay = customer.StartDay;
                        }
                        if (customer.EndDay != null)
                        {
                            cus.EndDay = customer.EndDay;
                        }
                    }
                }
            }
            //Allocate data from _allocateCus and save to DB
            List<Customer> Customers;
            using (var ts = new TransactionScope(TransactionScopeOption.Required))
            {
                try
                {
                    Customers = _allocateCus.Where(customer => customer.ResponsibleEmp != null
                                                                   && customer.StartDay != null
                                                                   && customer.EndDay != null).ToList();
                    foreach (var customer in Customers)
                    {
                        _allocation.FvAllocate(customer.Id, customer.ResponsibleEmp.Employee.Name, customer.StartDay, customer.EndDay);
                    }

                    ts.Complete();
                }
                catch (Exception ex)
                {
                    Models.HandleErrorInfo error = new Models.HandleErrorInfo(ex, "CusMgn", "Allocation");
                    return View("Error", error);
                }
            }

            //Can not duplicate use MMSEntities in Transaction -> write change status void outside Transaction
            //change status state to pre-inspector
            foreach (var customer in Customers)
            {
                var assets = _ap.GetAssetsByCusid(customer.Id);
                if (assets != null)
                {
                    foreach (var asset in assets)
                    {
                        _ap.UpdateStatus(asset.Id, Constants.STR_TYPE_STATUS_PRE_INSPECTOR);
                    }
                }
            }

            return RedirectToAction("Allocation");
        }

        public ActionResult AutoAllocation()
        {
            //get all customer have not allocated FV yet
            var customers = _cap.GetAllocationCus();
            //get all FV employees
            int idrespon = _eap.GetEmployeeByCode(User.Identity.Name).Employee.Id;
            var empFV = _eap.GetEmpsByRole(Constants.FV_ROLE)
                                .Where(x => x.Employee.IsLocked == false
                                    && x.Employee.Area.GroupId == _entities.MMS_GROUPs.FirstOrDefault(g => g.Responsibility == idrespon).Id)
                                    .OrderBy(x=> Guid.NewGuid())
                                .ToList();
            _allocateCus = _allocation.AutoAllocate(customers, empFV);
            SetViewBagData(null);
            return View("Allocation", _allocateCus.ToList());
        }


        #endregion

        #region Proccessing Board
        public ActionResult Processing()
        {
            try
            {
                _nameView = "Processing";
                SetViewBagData(null);
                _allocateCus = _cap.GetProcessingCus();
                return View(_allocateCus.ToList());
            }
            catch (Exception ex)
            {
                // To do: return error view or notify message
                return View();
            }
        }

        public ActionResult RemoveResponsibility(int cusId)
        {
            try
            {
                _allocation.RemoveResponsibility(cusId);
                //reset Valuation, Loan, Rate
                var assets = _ap.GetAssetsByCusid(cusId);
                foreach (var asset in assets)
                {
                        _ap.ResetAsset(asset.Id);
                }
                return RedirectToAction("Processing");

            }
            catch (Exception)
            {
                return RedirectToAction("Processing");
            }
        }

        #endregion

        #region Checking Board

        public ActionResult Checking()
        {
            try
            {
                _nameView = "Checking";
                SetViewBagData(null);
                _allocateCus = _cap.GetCheckingCus();
                return View(_allocateCus.ToList());
            }
            catch (Exception ex)
            {
                // To do: return error view or notify message
                return View();
            }
        }

        #endregion

        #region Store Result
        public ActionResult StoreResult()
        {
            _nameView = "StoreResult";
            SetViewBagData(null);
            _allocateCus = _cap.GetStoreResult();
            return View(_allocateCus);
        }

        #endregion

        #region CREATE VIEW
        /// <summary>
        /// Direct to create view
        /// Verb method: GET
        /// Url template: /CusMgn/Create
        /// </summary>
        /// <returns>Create view</returns>
        public ActionResult Create()
        {
            _nameView = "Create";
            SetViewBagData(null);
            Customer customer = new Customer();
            string id = _entities.MMS_CUSTOMERs.ToList().Last().Id.ToString();
            customer.Code = CodeGenerator.AutoGenerateCode(id);
            return View(customer);
        }

        /// <summary>
        /// Create new customer. If create succesfully, redirect to index page. 
        /// If not, notify message
        /// Vert method: POST
        /// Url template: /CusMgn/Create/...
        /// </summary>
        /// <param name="cus">Customer Information</param>
        /// <returns>If create succesfully, redirect to index page. 
        /// If not, notify message</returns>
        [HttpPost]
        public ActionResult Create(Customer cus)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    _cap = new CustomerAccessProvider();
                    bool isSuccess = _cap.AddCus(cus);
                    if (isSuccess)
                    {
                        return RedirectToAction("ListCusIndex");
                    }
                    else
                    {
                        return View(cus);
                    }
                }
                catch (Exception ex)
                {
                    // To do: show message, write log
                    return View(cus);
                }
            }
            else
            {
                return View(cus);
            }
        }
        #endregion CREATE VIEW

        #region Detail Cus
        public ActionResult Details(int id)
        {               
            var customer = _cap.GetCusById(id);
            if (_nameView != "StoreResult")
                return View("Details",customer);
            else return View("DetailsResult", customer);
        }
        #endregion

        #region Get List Customer
        public ActionResult ListCusIndex()
        {
            _nameView = "ListCustomer";
            SetViewBagData(null);
            _allocateCus = _cap.GetCusList().Where(x => x.Status == null).OrderByDescending(x => x.Code).ToList();
            return View(_allocateCus);
        }

        #endregion

        #region Edit Cus information
        public ActionResult Edit(int id)
        {
            var cus = _cap.GetCusById(id);
            SetViewBagData(id);
            return View(cus);
        }
    

        //
        // POST: /CusMgn/Edit/5

        [HttpPost]
        public ActionResult Edit(int id, Customer customer)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    // TODO: Add update logic here
                    if (_cap.UpdateCustomer(customer))
                        return RedirectToAction("ListCusIndex");
                    else return View();
                }
                catch
                {
                    return View(customer);
                }
            }
            else return View(customer);
        }
        #endregion

        public ActionResult FVCustomers()
        {
            _nameView = "FVCustomers";
            SetViewBagData(null);
            int idrespon = _eap.GetEmployeeByCode(User.Identity.Name).Employee.Id;
            _allocateCus = _cap.GetCusByFV(idrespon);
            return View(_allocateCus);
            //return RedirectToAction("Allocation", "CusMgn");
        }

        //View Bag for Edit include city and district
        public void SetViewBagData(int? id)
        {
            //get value cities and district for search
            ViewBag.Cities = _entities.MMS_AREAs.Select(c => c.CityName).Distinct();
            ViewBag.Districts = _entities.MMS_AREAs.Select(d => d.DistrictName);
            if (id != null)
            {
                var cus = _entities.MMS_CUSTOMERs.FirstOrDefault(c => c.Id == id);
                if (cus.MMS_AREA != null)
                {
                    ViewBag.Districts =
                        _entities.MMS_AREAs.Where(d => d.CityName == cus.MMS_AREA.CityName).Select(
                            d => d.DistrictName);
                }
            }

            //Search Field Name
            ViewBag.NameView = _nameView;
            //Get Emps with Role is FV
            if (Roles.Provider.IsUserInRole(User.Identity.Name,Constants.REVIEWER_ROLE))
            {
                int idrespon = _eap.GetEmployeeByCode(User.Identity.Name).Employee.Id;
                ViewBag.Emps = _eap.GetEmpsByRole(Constants.FV_ROLE)
                    .Where(x => x.Employee.IsLocked == false
                                &&
                                x.Employee.Area.GroupId ==
                                _entities.MMS_GROUPs.FirstOrDefault(g => g.Responsibility == idrespon).Id)
                    .Select(e => e.Employee.Name).ToList();
            }

        }

    }
}
